function config_debug_run:on_dismissed()
	self._init_data = nil;
	self._new_config = nil;
	self._new_setting = nil;
	self._setting = nil;
	self._target = nil;
	self._config = nil;
	self._toolset = nil;
end;

function config_debug_run:on_init()
	reload_cmake_project_settings();
	local toolsets = {};
	local targets = {};

	if TOOLSETS then
		for idx, toolset in ipairs(TOOLSETS) do
			table.insert(toolsets, toolset.name);
		end;
	end;
	if CMAKE_PROJECT_CBP then
		for idx, toolset in ipairs(CMAKE_PROJECT_CBP) do
			if toolset.output ~= nil then
				table.insert(targets, toolset.name);
			end;
		end;
	end;
	local init_data = {
		configs = {
			"Debug";
			"Release";
			"RelWithDebInfo";
			"MinSizeRel";
		};
		["toolsets"] = toolsets;
		["targets"] = targets;
		config = {
			[".targets"] = project_configs and project_configs[".targets"];
			[".build"] = {
				target = (menu_bar.get_cmake_default_target() or {}).name;
				toolset = (menu_bar.get_cmake_toolset() or "");
				config = (menu_bar.get_cmake_config() or "");
			};
		}
	};
	self._init_data = init_data;
	self._new_config = {};	-- modified self._init_data.config[".targets"]
	self._new_setting = nil;	-- modified self._setting
	self._setting = nil;	-- setting for current target/config/toolset
	self:init(init_data);
end;

function config_debug_run:on_apply()
	if project_configs == nil then
		-- not a cmake project
		return false;
	end;

	if self._new_config == nil then
		return true;
	end;

	local config = self._init_data.config[".targets"];

	local function env_parser(val)
		val = val.."\n";
		local env = {};
		for key, val in val:gmatch("([^=%s]+)=?([^\r\n]*)[\r\n]+") do
			env[key] = val;
		end;
		return env;
	end;

	local function write_cfg(target, setting_type, cfg_name, cfg_value, parser)
		if parser == nil then
			parser = function(val) return val; end;
		end;
		if cfg_value == nil or cfg_value == "" then
			if config[target] and config[target][cfg_name] and config[target][cfg_name][setting_type] then
				config[target][cfg_name][setting_type] = nil;
			end;
		else
			if config[target] == nil then
				config[target] = {};
			end;
			if config[target][cfg_name] == nil then
				config[target][cfg_name] = {};
			elseif type(config[target][cfg_name]) == "string" then
				if config[target][cfg_name] == cfg_value then
					return;
				end;
				config[target][cfg_name] = {default = config[target][cfg_name]};
			end;
			if config[target][cfg_name]["default"] == cfg_value then
				config[target][cfg_name][setting_type] = nil;
			else
				config[target][cfg_name][setting_type] = parser(cfg_value);
			end;
		end;
	end;
	-- print("new==>")
	-- print_table(self._new_config);

	for target, settings in pairs(self._new_config) do
		for setting_type, setting in pairs(settings) do
			write_cfg(target, setting_type, "argument", setting.argument);
			write_cfg(target, setting_type, "cwd", setting.cwd);
			write_cfg(target, setting_type, "environment", setting.environment, env_parser);
		end;
		if sizeof(config[target].argument) == 0 then
			config[target].argument = nil;
		end;
		if sizeof(config[target].cwd) == 0 then
			config[target].cwd = nil;
		end;
		if sizeof(config[target].environment) == 0 then
			config[target].environment = nil;
		end;
		if sizeof(config[target]) == 0 then
			config[target] = nil;
		end;
	end;

	project_configs[".targets"] = config;
	-- print("merged==>");
	-- print_table(config);
	save_cmake_project_settings(true);
	return true;
end;

function config_debug_run:on_cancel()
	self._new_config = {};
	self:on_selection_changed(self._target, self._config, self._toolset);
end;

function config_debug_run:_get_new_setting()
	if self._new_setting == nil then
		self._new_setting = table.clone(self._setting);
		self._new_config[self._target] = self._new_config[self._target] or {};
		self._new_config[self._target][self._toolset.."-"..self._config] = self._new_setting;
	end;
	return self._new_setting;
end;

function config_debug_run:on_argument_changed()
	self:_get_new_setting().argument = self.argument;
end;

function config_debug_run:on_cwd_changed()
	self:_get_new_setting().cwd = self.cwd;
end;

function config_debug_run:on_environment_changed()
	self:_get_new_setting().environment = self.environment;
end;

function config_debug_run:update_setting()
	self.argument = self._setting.argument;
	self.cwd = self._setting.cwd;
	self.environment = self._setting.environment;
end;
	
function config_debug_run:on_selection_changed(target, config, toolset)
	self._new_setting = nil;
	self._setting = nil;
	self._target = target;
	self._config = config;
	self._toolset = toolset;

	local setting_name = toolset.."-"..config;
	local target_cfg = self._new_config and self._new_config[target] and self._new_config[target][setting_name];
	if target_cfg then
		self._setting = target_cfg;
		self:update_setting();
		return;
	end;

	target_cfg = self._init_data.config[".targets"] and self._init_data.config[".targets"][target];
	if target_cfg == nil then
		self._setting = {
			argument = "";
			cwd = "";
			environment = "";
		};
		self:update_setting();
		return;
	end;

	local function get_setting(settings, name, def_val)
		local val = settings[name];
		if type(val) == "string" then
			return val;
		end;
		if type(val) == "table" then
			return val[setting_name] or val["default"] or def_val;
		end;
		return def_val;
	end;

	local function make_env_string(env)
		if env == nil then
			return "";
		end;
		local keys = table.keys(env);
		table.sort(keys);
		local envs = {};
		for idx, key in ipairs(keys) do
			table.insert(envs, key .. "=" .. (env[key]));
		end;
		return table.concat(envs, "\r\n");
	end;

	self._setting = {
		argument = get_setting(target_cfg, "argument", "");
		cwd = get_setting(target_cfg, "cwd", "");
		environment = make_env_string(get_setting(target_cfg, "environment", nil));
	};
	self:update_setting();
end;
